#include "usb.h"

USBHID hid;

class TOUCH_SCREEN : public USBHIDDevice
{
public:
    // HID init
    TOUCH_SCREEN()
    {
        static bool init = false;
        if (!init)
        {
            hid.addDevice(this, sizeof(init_packet));
            init = true;
        }
    }

    uint16_t _onGetFeature(uint8_t report_id, uint8_t *buffer, uint16_t len)
    {
        buffer[0] = TOUCH_LOCAL_NUM;
        buffer[1] = REPORTID_TOUCHPAD;
        return sizeof(buffer);
    }

    // Windows -> GetDescriptor
    uint16_t _onGetDescriptor(uint8_t *buffer)
    {
        memcpy(buffer, init_packet, sizeof(init_packet));
        return sizeof(init_packet);
    }

    void begin(void)
    {
        hid.begin();
    }

    // 发送HID Packet
    bool send_touch(uint8_t *value) { return hid.SendReport(REPORTID_TOUCHPAD, value, 9); }
    bool send_keyboard_1(uint8_t *value) { return hid.SendReport(KEYBOARD_ID, value, 8); }
    bool send_keyboard_2(uint8_t *value) { return hid.SendReport(KEYBOARD_ID + 1, value, 8); }
};

TOUCH_SCREEN touch;

volatile uint8_t USB_OTG::touch_data[64] = {0};

uint8_t USB_OTG::HID_state = 0;

bool USB_OTG::HID_ready()
{
    bool state = hid.ready();
    usb.HID_state = state ? 1 : 0;
    return state;
}

void USB_OTG::HID_end()
{
    usb.HID_state = 0;
    hid.end();
}

// 串口参考 https://github.com/Sucareto/Mai2Touch/blob/main/Mai2Touch/Mai2Touch.ino

void USB_OTG::init()
{
    USB.usbPower(2000);
    USB.productName(USB_NAME);
    USB.begin();
    touch.begin();
    usb.HID_state = 1;
}

// 触摸反馈
// X: 0-32768 Y:0-32768 STATE: 0-255 ID: 0-19 COUNT: 1-20
void IRAM_ATTR USB_OTG::Send_touchscreen(uint8_t On /*是否按下*/, uint16_t X_axis /*X坐标*/, uint16_t Y_axis /*Y坐标*/, uint8_t Id /*点位ID*/, uint8_t Multi /*同时存在位点*/, millis_t timer /*同步时间*/)
{
    if (!usb.HID_state)
        return;
    static uint8_t TouchData[9];
    TouchData[0] = On;                         // Touch_id
    TouchData[1] = Id;                         // Touch_id
    TouchData[2] = X_axis & 0xFF;              // X lsb
    TouchData[3] = X_axis >> 8 & 0xFF;         // X msb
    TouchData[4] = Y_axis & 0xFF;              // Y lsb
    TouchData[5] = Y_axis >> 8 & 0xFF;         // Y msb
    TouchData[6] = (timer * 10) & 0xFF;        // Scan time lsb
    TouchData[7] = ((timer * 10) >> 8) & 0xFF; // Scan time msb
    TouchData[8] = Multi;
    touch.send_touch(TouchData);
}


//键盘反馈
void IRAM_ATTR USB_OTG::Send_keyboard(uint8_t * pull_down) {
    if (!usb.HID_state)
        return;
    static uint8_t keyboardData[8] = {0};
    static uint8_t _keyboardData[8] = {0};
    keyboardData[0] = 0;
    keyboardData[1] = 0;
    keyboardData[2] = pull_down[0];
    keyboardData[3] = pull_down[1];
    keyboardData[4] = pull_down[2];
    keyboardData[5] = pull_down[3];
    keyboardData[6] = pull_down[4];
    keyboardData[7] = pull_down[5];
    _keyboardData[0] = 0;
    _keyboardData[1] = 0;
    _keyboardData[2] = pull_down[6];
    _keyboardData[3] = pull_down[7];
    _keyboardData[4] = pull_down[8];
    _keyboardData[5] = pull_down[9];
    _keyboardData[6] = pull_down[10];
    _keyboardData[7] = pull_down[11];
    touch.send_keyboard_1(keyboardData);
    touch.send_keyboard_2(_keyboardData);
}
/*
int STARTX = 18000;
int STARTY = 18000;
int STARTR = 100;
int iX, iY;
for (int i = 0; i < 100 * 18; i++)
{
    TouchData[0] = 0b10111101;
    TouchData[1] = 0x01;
    iX = STARTX + (STARTR * cos(2 * PI * i / 100) + STARTR * (2 * PI * i / 100) * sin(2 * PI * i / 100)) * 3 / 4;
    iY = STARTY + STARTR * sin(2 * PI * i / 100) - STARTR * (2 * PI * i / 100) * cos(2 * PI * i / 100);
    TouchData[2] = ((int)(iX)) & 0xFF;
    TouchData[3] = ((int)(iX)) >> 8 & 0xFF;
    TouchData[4] = ((int)(iY)) & 0xFF;
    TouchData[5] = ((int)(iY)) >> 8 & 0xFF;
    TouchData[6] = (i * 10) & 0xFF;
    TouchData[7] = (i * 10 >> 8) & 0xFF;
    TouchData[8] = 0x02;
    touch.send(TouchData);

    TouchData[0] = 0b10111111;
    TouchData[1] = 0x02;
    iX = STARTX + (STARTR * cos(2 * PI * i / 100) + STARTR * (2 * PI * i / 100) * sin(2 * PI * i / 100)) * 3 / 4;
    iY = STARTY + STARTR * sin(2 * PI * i / 100) - STARTR * (2 * PI * i / 100) * cos(2 * PI * i / 100);
    TouchData[2] = ((int)(iX - 5000)) & 0xFF;
    TouchData[3] = ((int)(iX - 5000)) >> 8 & 0xFF;
    TouchData[4] = ((int)(iY)) & 0xFF;
    TouchData[5] = ((int)(iY)) >> 8 & 0xFF;
    TouchData[6] = (i * 10) & 0xFF;
    TouchData[7] = (i * 10 >> 8) & 0xFF;
    TouchData[8] = 0;
    touch.send(TouchData);
    vTaskDelay(1);
}
* /

    // vTaskDelay(1);
    /*
    for (uint32_t i = 0; i < ms; i++)
    {

        TouchData[0] = State;
        TouchData[1] = id;                          // Touch_id
        TouchData[2] = ((int)(X_axis)) & 0xFF;      // X lsb
        TouchData[3] = ((int)(X_axis)) >> 8 & 0xFF; // X msb
        TouchData[4] = ((int)(Y_axis)) & 0xFF;      // Y lsb
        TouchData[5] = ((int)(Y_axis)) >> 8 & 0xFF; // Y msb
        TouchData[6] = (time * 10) & 0xFF;          // Scan time lsb
        TouchData[7] = ((time * 10) >> 8) & 0xFF;   // Scan time msb
        TouchData[8] = count;

        touch.send(TouchData);
        time++;
        vTaskDelay(1);
    }
    */
/* 摘抄测试用 https://www.lab-z.com/esp32tch/
    int STARTX = 18000;
    int STARTY = 18000;
    int STARTR = 100;
    int iX, iY;
    for (int i = 0; i < STEP * 18; i++)
    {
        TouchData[0] = 0x81;
        TouchData[1] = 0x01;
        iX = STARTX + (STARTR * cos(2 * PI * i / STEP) + STARTR * (2 * PI * i / STEP) * sin(2 * PI * i / STEP)) * 3 / 4;
        iY = STARTY + STARTR * sin(2 * PI * i / STEP) - STARTR * (2 * PI * i / STEP) * cos(2 * PI * i / STEP);
        TouchData[2] = ((int)(iX)) & 0xFF;
        TouchData[3] = ((int)(iX)) >> 8 & 0xFF;
        TouchData[4] = ((int)(iY)) & 0xFF;
        TouchData[5] = ((int)(iY)) >> 8 & 0xFF;
        TouchData[6] = (millis() * 10) & 0xFF;
        TouchData[7] = (millis() * 10 >> 8) & 0xFF;
        TouchData[8] = 0x01;
        touch.send(TouchData);
        vTaskDelay(20);
    }
    */
/*
TouchData[0] = 0xaa;
TouchData[1] = 0x21;
TouchData[2] = 0x00;
TouchData[3] = 0x00;
TouchData[4] = 0x01;
TouchData[5] = 0x00;
TouchData[6] = 0x01;
TouchData[7] = 0x10;
TouchData[8] = 0x00;
TouchData[9] = 0x10;
TouchData[10] = 0x00;
TouchData[11] = 0x0;
TouchData[12] = 0x0;
*/
